/*
 * Copyright (C) 2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include <check.h>
#include "PlanetWars2dRT-core/specific/controller/player_robots.h"
#include "PlanetWars2dRT-core/specific/controller/game_playing.h"
#include "PlanetWars2dRT-core/specific/controller/game_end_result.h"
#include "PlanetWars2dRT-core/specific/model/game_players.h"
#include "PlanetWars2dRT-core/specific/model/universes.h"
#include "PlanetWars2dRT-core/specific/model/universe_planets.h"
#include "PlanetWars2dRT-core/specific/model/ship_move.h"
#include "PlanetWars2dRT-core/specific/model/ship_power.h"
#include "PlanetWars2dRT-core/utils/color_rgb_const.h"


struct game_playing_t a_game_playing;

void
tests_setup_init(void)
{
  game_playing_init_first_time_only_default(&a_game_playing);
  game_state_set_pause(&a_game_playing.state, false);
  
  struct player_t robot;
  player_init_first_time_only(&robot);
  player_set_name(&robot, "Robot 1");
  robot.color = COLOR_RGB_RED;
  ck_assert(game_add_player(&a_game_playing.game, &robot));
  player_set_name(&robot, "Robot 2");
  robot.color = COLOR_RGB_GREEN;
  ck_assert(game_add_player(&a_game_playing.game, &robot));
  player_set_name(&robot, "Robot 3");
  robot.color = COLOR_RGB_BLUE;
  ck_assert(game_add_player(&a_game_playing.game, &robot));
  player_set_name(&robot, "Robot 4");
  robot.color = COLOR_RGB_YELLOW;
  ck_assert(game_add_player(&a_game_playing.game, &robot));
}

void
tests_setup_free(void)
{
  game_playing_destructor(&a_game_playing);
}


static inline
void
reduce_planets_life(universe_t* a_universe, unsigned int value)
{
  const size_t nb = universe_get_nb_planets(a_universe);
  for(size_t i=0; i < nb; ++i)
    {
      planet_t* p = universe_get_planet_no_check(a_universe, i);
      p->life_current = p->life_max = value;
    }
}

static inline
void
reduce_planets_life_to_1(universe_t* a_universe)
{
  reduce_planets_life(a_universe, 1);
}

static inline
void
increase_planets_production(universe_t* a_universe)
{
  const size_t nb = universe_get_nb_planets(a_universe);
  for(size_t i=0; i < nb; ++i)
    {
      planet_t* p = universe_get_planet_no_check(a_universe, i);
      p->producing_capacity    = 5;
      p->nb_updates_to_produce = 1;
    }
}


void
test_win_inactive_generic(player_act_t act,
			  universe_basic_getter_t universe_getter)
{
  struct player_t* robot = game_get_player_no_check(&a_game_playing.game, 0);
  ck_assert_ptr_ne(robot, NULL);
  robot->act = act;
  
  bool success;
  a_game_playing.game.universe = universe_getter(&success);
  ck_assert(success);
  reduce_planets_life_to_1(&a_game_playing.game.universe);
  increase_planets_production(&a_game_playing.game.universe);
  ck_assert(game_playing_run(&a_game_playing));
  ck_assert_uint_eq(game_get_winner_index(&a_game_playing.game), 0);
}

START_TEST(test_win_inactive_very_stupid_rusher)
{
  test_win_inactive_generic(player_robot_very_lazy_stupid_rusher_act,
			    get_universe_hard_coded_line_3_planets);
}
END_TEST

START_TEST(test_win_inactive_stupid_rusher)
{
  test_win_inactive_generic(player_robot_lazy_stupid_rusher_act,
			    get_universe_hard_coded_line_3_planets);
}
END_TEST

START_TEST(test_win_inactive_easy)
{
  test_win_inactive_generic(player_robot_lazy_easy,
			    get_universe_hard_coded_line_3_planets);
}
END_TEST

START_TEST(test_win_inactive_normal)
{
  test_win_inactive_generic(player_robot_lazy_normal,
			    get_universe_hard_coded_line_3_planets);
}
END_TEST


Suite*
player_robots_suite(void)
{
  Suite* s = suite_create("Player robots");
  
  TCase* tc_win_inactive = tcase_create("Win against inactive");
  tcase_add_checked_fixture(tc_win_inactive,
			    tests_setup_init, tests_setup_free);
  tcase_add_test(tc_win_inactive, test_win_inactive_very_stupid_rusher);
  tcase_add_test(tc_win_inactive, test_win_inactive_stupid_rusher);
  tcase_add_test(tc_win_inactive, test_win_inactive_easy);
  tcase_add_test(tc_win_inactive, test_win_inactive_normal);
  suite_add_tcase(s, tc_win_inactive);
  
  return s;
}

int
main(void)
{
  size_t number_failed;
  Suite* s;
  SRunner* sr;

  s = player_robots_suite();
  sr = srunner_create(s);
  
  srunner_run_all(sr, CK_NORMAL);
  number_failed = srunner_ntests_failed(sr);
  srunner_free(sr);
  
  return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
